Construir um agente inteligente capaz de operar na bolsa de valores a partir de experimentos de compra e venda de ações. Dado um saldo inicial, o modelo deve apresentar o resultado (lucro) a ser obtido depois de ações de compra e venda.
Esta análise de dados tem como único propósito a demonstração e teste da implementação básica de um agente inteligente. Não deve ser interpretada como um conselho de atuação no mercado de ações.
!pip install -q plotly
#Imports
import random
import plotly.graph_objects as go
import pandas as pd
import numpy as np
from datetime import datetime
df=pd.read_csv('dataset.csv')
df.shape
(506, 11)
df.head()
| Date | AAPL.Open | AAPL.High | AAPL.Low | AAPL.Close | AAPL.Volume | AAPL.Adjusted | dn | mavg | up | direction | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2015-02-17 | 127.489998 | 128.880005 | 126.919998 | 127.830002 | 63152400 | 122.905254 | 106.741052 | 117.927667 | 129.114281 | Increasing |
| 1 | 2015-02-18 | 127.629997 | 128.779999 | 127.449997 | 128.720001 | 44891700 | 123.760965 | 107.842423 | 118.940333 | 130.038244 | Increasing |
| 2 | 2015-02-19 | 128.479996 | 129.029999 | 128.330002 | 128.449997 | 37362400 | 123.501363 | 108.894245 | 119.889167 | 130.884089 | Decreasing |
| 3 | 2015-02-20 | 128.619995 | 129.500000 | 128.050003 | 129.500000 | 48948400 | 124.510914 | 109.785449 | 120.763500 | 131.741551 | Increasing |
| 4 | 2015-02-23 | 130.020004 | 133.000000 | 129.660004 | 133.000000 | 70974100 | 127.876074 | 110.372516 | 121.720167 | 133.067817 | Increasing |
Facilitando a visualização da variação dos preços por meio de um gráfico de vela.
#Candlestick
fig=go.Figure(data=[go.Candlestick(x=df['Date'],
open=df['AAPL.Open'],
high=df['AAPL.High'],
low=df['AAPL.Low'],
close=df['AAPL.Close'])])
fig.show()
#Trabalhando com a cotação de fechamento da ação da Apple
precos=df['AAPL.Close'].values
type(precos)
numpy.ndarray
#Configuração do Q-Learning
print('\nDefinindo os Hiperparâmetros do Q-Learning')
num_episodios=1000
alfa=0.1
gama=0.99
epsilon=0.1
Definindo os Hiperparâmetros do Q-Learning
#Configuração do ambiente de negociação
print('\nConfigurando o Ambiente de Negociação')
acoes=['comprar','vender','manter']
saldo_inicial=1000
num_acoes_inicial=0
Configurando o Ambiente de Negociação
#Função para executar uma ação e retornar a recompensa e o próximo estado
def executar_acao(estado, acao, saldo, num_acoes, preco):
#Comprar
if acao==0:
if saldo>=preco:
num_acoes+=1
saldo-=preco
#Vender
elif acao==1:
if num_acoes>0:
num_acoes-=1
saldo+=preco
#Define o lucro
lucro=saldo+num_acoes*preco-saldo_inicial
return (saldo, num_acoes, lucro)
#Inicializar a tabela Q
print('\nInicializando a Tabela Q...')
q_tabela=np.zeros((len(precos), len(acoes)))
Inicializando a Tabela Q...
#Treinamento
print('\nInicializando o Treinamento...')
for _ in range(num_episodios):
#Define o saldo
saldo=saldo_inicial
#Define o número de acoes
num_acoes=num_acoes_inicial
#Loop
for i, preco in enumerate(precos[:-1]):
estado=i
#Escolher a ação usando a política epsilon-greedy
if np.random.random()<epsilon:
acao=random.choice(range(len(acoes)))
else:
acao=np.argmax(q_tabela[estado])
#Executar a ação e obter a recompensa e o próximo estado
saldo, num_acoes, lucro=executar_acao(estado, acao, saldo, num_acoes, preco)
prox_estado=i+1
#Atualizar a tabela Q
q_tabela[estado][acao]+=alfa*(lucro+gama*np.max(q_tabela[prox_estado])-q_tabela[estado][acao])
print('\nTreinamento Concluído')
Inicializando o Treinamento... Treinamento Concluído
#Valores iniciais para testar o agente
saldo=saldo_inicial
num_acoes=num_acoes_inicial
print('\nExecutando o Agente...')
for i, preco in enumerate(precos[:-1]):
estado=i
acao=np.argmax(q_tabela[estado])
saldo, num_acoes, _=executar_acao(estado, acao, saldo, num_acoes, preco)
print('\nExecução Concluída')
Executando o Agente... Execução Concluída
num_acoes
5
precos[-1]
135.350006
#Vendendo todas as ações no último preço
saldo+=num_acoes*precos[-1]
lucro=saldo-saldo_inicial
lucro_final=round(lucro,2)
print(f"\nComeçamos a Negociação com saldo inicial de 1000 e tivemos lucro de: {lucro_final}")
Começamos a Negociação com saldo inicial de 1000 e tivemos lucro de: 73.22